home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / BOXES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  18.6 KB  |  1,058 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                boxes.c
  3. *
  4. *  This module implements the box primitive.
  5. *  This file was written by Alexander Enzmann.  He wrote the code for
  6. *  boxes and generously provided us these enhancements.
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. #include "frame.h"
  27. #include "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "bbox.h"
  31. #include "boxes.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40.  
  41. /* Minimal intersection depth. */
  42.  
  43. #define DEPTH_TOLERANCE 1.0e-6
  44.  
  45. /* Two values are equal if their difference is small than CLOSE_TOLERANCE. */
  46.  
  47. #define CLOSE_TOLERANCE 1.0e-6
  48.  
  49. /* Side hit. */
  50.  
  51. #define SIDE_X_0 1
  52. #define SIDE_X_1 2
  53. #define SIDE_Y_0 3
  54. #define SIDE_Y_1 4
  55. #define SIDE_Z_0 5
  56. #define SIDE_Z_1 6
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Static functions
  62. ******************************************************************************/
  63. static int  All_Box_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  64. static int  Inside_Box PARAMS((VECTOR point, OBJECT *Object));
  65. static void Box_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
  66. static void Translate_Box PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  67. static void Rotate_Box PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  68. static void Scale_Box PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  69. static void Transform_Box PARAMS((OBJECT *Object, TRANSFORM *Trans));
  70. static void Invert_Box PARAMS((OBJECT *Object));
  71.  
  72.  
  73.  
  74. /*****************************************************************************
  75. * Local variables
  76. ******************************************************************************/
  77.  
  78. METHODS Box_Methods =
  79. {
  80.   All_Box_Intersections,
  81.   Inside_Box, Box_Normal,
  82.   Copy_Box, Translate_Box, Rotate_Box, Scale_Box, Transform_Box,
  83.   Invert_Box, Destroy_Box
  84. };
  85.  
  86.  
  87.  
  88. /*****************************************************************************
  89. *
  90. * FUNCTION
  91. *
  92. *   All_Box_Intersections
  93. *
  94. * INPUT
  95. *
  96. * OUTPUT
  97. *
  98. * RETURNS
  99. *
  100. * AUTHOR
  101. *
  102. *   Alexander Enzmann
  103. *
  104. * DESCRIPTION
  105. *
  106. *   -
  107. *
  108. * CHANGES
  109. *
  110. *   -
  111. *
  112. ******************************************************************************/
  113.  
  114. static int All_Box_Intersections(Object, Ray, Depth_Stack)
  115. OBJECT *Object;
  116. RAY *Ray;
  117. ISTACK *Depth_Stack;
  118. {
  119.   int Intersection_Found;
  120.   int Side1, Side2;
  121.   DBL Depth1, Depth2;
  122.   VECTOR IPoint;
  123.  
  124.   Increase_Counter(stats[Ray_Box_Tests]);
  125.  
  126.   Intersection_Found = FALSE;
  127.  
  128.   if (Intersect_Box(Ray, (BOX *)Object, &Depth1, &Depth2, &Side1, &Side2))
  129.   {
  130.     if (Depth1 > DEPTH_TOLERANCE)
  131.     {
  132.       VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
  133.  
  134.       if (Point_In_Clip(IPoint, Object->Clip))
  135.       {
  136.         push_entry_i1(Depth1,IPoint,Object,Side1,Depth_Stack);
  137.  
  138.         Intersection_Found = TRUE;
  139.       }
  140.     }
  141.  
  142.     VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
  143.  
  144.     if (Point_In_Clip(IPoint, Object->Clip))
  145.     {
  146.       push_entry_i1(Depth2,IPoint,Object,Side2,Depth_Stack);
  147.  
  148.       Intersection_Found = TRUE;
  149.     }
  150.   }
  151.  
  152.   if (Intersection_Found)
  153.   {
  154.     Increase_Counter(stats[Ray_Box_Tests_Succeeded]);
  155.   }
  156.  
  157.   return (Intersection_Found);
  158. }
  159.  
  160.  
  161.  
  162. /*****************************************************************************
  163. *
  164. * FUNCTION
  165. *
  166. *   Intersect_Box
  167. *
  168. * INPUT
  169. *
  170. * OUTPUT
  171. *
  172. * RETURNS
  173. *
  174. * AUTHOR
  175. *
  176. *   Alexander Enzmann
  177. *
  178. * DESCRIPTION
  179. *
  180. *   -
  181. *
  182. * CHANGES
  183. *
  184. *   Sep 1994 : Added code to decide which side was hit in the case
  185. *              intersection points are close to each other. This removes
  186. *              some ugly artefacts one could observe at the corners of
  187. *              boxes due to the usage of the wrong normal vector. [DB]
  188. *
  189. ******************************************************************************/
  190.  
  191. int Intersect_Box(Ray, box, Depth1, Depth2, Side1, Side2)
  192. RAY *Ray;
  193. BOX *box;
  194. DBL *Depth1, *Depth2;
  195. int *Side1, *Side2;
  196. {
  197.   int smin = 0, smax = 0;    /* Side hit for min/max intersection. */
  198.   DBL t, tmin, tmax;
  199.   VECTOR P, D;
  200.  
  201.   /* Transform the point into the boxes space */
  202.  
  203.   if (box->Trans != NULL)
  204.   {
  205.     MInvTransPoint(P, Ray->Initial, box->Trans);
  206.     MInvTransDirection(D, Ray->Direction, box->Trans);
  207.   }
  208.   else
  209.   {
  210.     Assign_Vector(P, Ray->Initial);
  211.     Assign_Vector(D, Ray->Direction);
  212.   }
  213.  
  214.   tmin = 0.0;
  215.   tmax = BOUND_HUGE;
  216.  
  217.   /*
  218.    * Sides first.
  219.    */
  220.  
  221.   if (D[X] < -EPSILON)
  222.   {
  223.     t = (box->bounds[0][X] - P[X]) / D[X];
  224.  
  225.     if (t < tmin) return(FALSE);
  226.  
  227.     if (t <= tmax)
  228.     {
  229.       smax = SIDE_X_0;
  230.       tmax = t;
  231.     }
  232.  
  233.     t = (box->bounds[1][X] - P[X]) / D[X];
  234.  
  235.     if (t >= tmin)
  236.     {
  237.       if (t > tmax) return(FALSE);
  238.  
  239.       smin = SIDE_X_1;
  240.       tmin = t;
  241.     }
  242.   }
  243.   else
  244.   {
  245.     if (D[X] > EPSILON)
  246.     {
  247.       t = (box->bounds[1][X] - P[X]) / D[X];
  248.  
  249.       if (t < tmin) return(FALSE);
  250.  
  251.       if (t <= tmax)
  252.       {
  253.         smax = SIDE_X_1;
  254.         tmax = t;
  255.       }
  256.  
  257.       t = (box->bounds[0][X] - P[X]) / D[X];
  258.  
  259.       if (t >= tmin)
  260.       {
  261.         if (t > tmax) return(FALSE);
  262.  
  263.         smin = SIDE_X_0;
  264.         tmin = t;
  265.       }
  266.     }
  267.     else
  268.     {
  269.       if ((P[X] < box->bounds[0][X]) || (P[X] > box->bounds[1][X]))
  270.       {
  271.         return(FALSE);
  272.       }
  273.     }
  274.   }
  275.  
  276.   /*
  277.    * Check Top/Bottom.
  278.    */
  279.  
  280.   if (D[Y] < -EPSILON)
  281.   {
  282.     t = (box->bounds[0][Y] - P[Y]) / D[Y];
  283.  
  284.     if (t < tmin) return(FALSE);
  285.  
  286.     if (t <= tmax - CLOSE_TOLERANCE)
  287.     {
  288.       smax = SIDE_Y_0;
  289.       tmax = t;
  290.     }
  291.     else
  292.     {
  293.       /*
  294.        * If intersection points are close to each other find out
  295.        * which side to use, i.e. is most probably hit. [DB 9/94]
  296.        */
  297.  
  298.       if (t <= tmax + CLOSE_TOLERANCE)
  299.       {
  300.         if (-D[Y] > fabs(D[X])) smax = SIDE_Y_0;
  301.       }
  302.     }
  303.  
  304.     t = (box->bounds[1][Y] - P[Y]) / D[Y];
  305.  
  306.     if (t >= tmin + CLOSE_TOLERANCE)
  307.     {
  308.       if (t > tmax) return(FALSE);
  309.  
  310.       smin = SIDE_Y_1;
  311.       tmin = t;
  312.     }
  313.     else
  314.     {
  315.       /*
  316.        * If intersection points are close to each other find out
  317.        * which side to use, i.e. is most probably hit. [DB 9/94]
  318.        */
  319.  
  320.       if (t >= tmin - CLOSE_TOLERANCE)
  321.       {
  322.         if (-D[Y] > fabs(D[X])) smin = SIDE_Y_1;
  323.       }
  324.     }
  325.   }
  326.   else
  327.   {
  328.     if (D[Y] > EPSILON)
  329.     {
  330.       t = (box->bounds[1][Y] - P[Y]) / D[Y];
  331.  
  332.       if (t < tmin) return(FALSE);
  333.  
  334.       if (t <= tmax - CLOSE_TOLERANCE)
  335.       {
  336.         smax = SIDE_Y_1;
  337.         tmax = t;
  338.       }
  339.       else
  340.       {
  341.         /*
  342.          * If intersection points are close to each other find out
  343.          * which side to use, i.e. is most probably hit. [DB 9/94]
  344.          */
  345.  
  346.         if (t <= tmax + CLOSE_TOLERANCE)
  347.         {
  348.           if (D[Y] > fabs(D[X])) smax = SIDE_Y_1;
  349.         }
  350.       }
  351.  
  352.       t = (box->bounds[0][Y] - P[Y]) / D[Y];
  353.  
  354.       if (t >= tmin + CLOSE_TOLERANCE)
  355.       {
  356.         if (t > tmax) return(FALSE);
  357.  
  358.         smin = SIDE_Y_0;
  359.         tmin = t;
  360.       }
  361.       else
  362.       {
  363.         /*
  364.          * If intersection points are close to each other find out
  365.          * which side to use, i.e. is most probably hit. [DB 9/94]
  366.          */
  367.  
  368.         if (t >= tmin - CLOSE_TOLERANCE)
  369.         {
  370.           if (D[Y] > fabs(D[X])) smin = SIDE_Y_0;
  371.         }
  372.       }
  373.     }
  374.     else
  375.     {
  376.       if ((P[Y] < box->bounds[0][Y]) || (P[Y] > box->bounds[1][Y]))
  377.       {
  378.         return(FALSE);
  379.       }
  380.     }
  381.   }
  382.  
  383.   /* Now front/back */
  384.  
  385.   if (D[Z] < -EPSILON)
  386.   {
  387.     t = (box->bounds[0][Z] - P[Z]) / D[Z];
  388.  
  389.     if (t < tmin) return(FALSE);
  390.  
  391.     if (t <= tmax - CLOSE_TOLERANCE)
  392.     {
  393.       smax = SIDE_Z_0;
  394.       tmax = t;
  395.     }
  396.     else
  397.     {
  398.       /*
  399.        * If intersection points are close to each other find out
  400.        * which side to use, i.e. is most probably hit. [DB 9/94]
  401.        */
  402.  
  403.       if (t <= tmax + CLOSE_TOLERANCE)
  404.       {
  405.         switch (smax)
  406.         {
  407.           case SIDE_X_0 :
  408.           case SIDE_X_1 : if (-D[Z] > fabs(D[X])) smax = SIDE_Z_0; break;
  409.  
  410.           case SIDE_Y_0 :
  411.           case SIDE_Y_1 : if (-D[Z] > fabs(D[Y])) smax = SIDE_Z_0; break;
  412.         }
  413.       }
  414.     }
  415.  
  416.     t = (box->bounds[1][Z] - P[Z]) / D[Z];
  417.  
  418.     if (t >= tmin + CLOSE_TOLERANCE)
  419.     {
  420.       if (t > tmax) return(FALSE);
  421.  
  422.       smin = SIDE_Z_1;
  423.       tmin = t;
  424.     }
  425.     else
  426.     {
  427.       /*
  428.        * If intersection points are close to each other find out
  429.        * which side to use, i.e. is most probably hit. [DB 9/94]
  430.        */
  431.  
  432.       if (t >= tmin - CLOSE_TOLERANCE)
  433.       {
  434.         switch (smin)
  435.         {
  436.           case SIDE_X_0 :
  437.           case SIDE_X_1 : if (-D[Z] > fabs(D[X])) smin = SIDE_Z_1; break;
  438.  
  439.           case SIDE_Y_0 :
  440.           case SIDE_Y_1 : if (-D[Z] > fabs(D[Y])) smin = SIDE_Z_1; break;
  441.         }
  442.       }
  443.     }
  444.   }
  445.   else
  446.   {
  447.     if (D[Z] > EPSILON)
  448.     {
  449.       t = (box->bounds[1][Z] - P[Z]) / D[Z];
  450.  
  451.       if (t < tmin) return(FALSE);
  452.  
  453.       if (t <= tmax - CLOSE_TOLERANCE)
  454.       {
  455.         smax = SIDE_Z_1;
  456.         tmax = t;
  457.       }
  458.       else
  459.       {
  460.         /*
  461.          * If intersection points are close to each other find out
  462.          * which side to use, i.e. is most probably hit. [DB 9/94]
  463.          */
  464.  
  465.         if (t <= tmax + CLOSE_TOLERANCE)
  466.         {
  467.           switch (smax)
  468.           {
  469.             case SIDE_X_0 :
  470.             case SIDE_X_1 : if (D[Z] > fabs(D[X])) smax = SIDE_Z_1; break;
  471.  
  472.             case SIDE_Y_0 :
  473.             case SIDE_Y_1 : if (D[Z] > fabs(D[Y])) smax = SIDE_Z_1; break;
  474.           }
  475.         }
  476.       }
  477.  
  478.       t = (box->bounds[0][Z] - P[Z]) / D[Z];
  479.  
  480.       if (t >= tmin + CLOSE_TOLERANCE)
  481.       {
  482.         if (t > tmax) return(FALSE);
  483.  
  484.         smin = SIDE_Z_0;
  485.         tmin = t;
  486.       }
  487.       else
  488.       {
  489.         /*
  490.          * If intersection points are close to each other find out
  491.          * which side to use, i.e. is most probably hit. [DB 9/94]
  492.          */
  493.  
  494.         if (t >= tmin - CLOSE_TOLERANCE)
  495.         {
  496.           switch (smin)
  497.           {
  498.             case SIDE_X_0 :
  499.             case SIDE_X_1 : if (D[Z] > fabs(D[X])) smin = SIDE_Z_0; break;
  500.  
  501.             case SIDE_Y_0 :
  502.             case SIDE_Y_1 : if (D[Z] > fabs(D[Y])) smin = SIDE_Z_0; break;
  503.           }
  504.         }
  505.       }
  506.     }
  507.     else
  508.     {
  509.       if ((P[Z] < box->bounds[0][Z]) || (P[Z] > box->bounds[1][Z]))
  510.       {
  511.         return(FALSE);
  512.       }
  513.     }
  514.   }
  515.  
  516.   if (tmax < DEPTH_TOLERANCE)
  517.   {
  518.     return (FALSE);
  519.   }
  520.  
  521.   *Depth1 = tmin;
  522.   *Depth2 = tmax;
  523.  
  524.   *Side1 = smin;
  525.   *Side2 = smax;
  526.  
  527.   return(TRUE);
  528. }
  529.  
  530.  
  531.  
  532. /*****************************************************************************
  533. *
  534. * FUNCTION
  535. *
  536. *   Inside_Box
  537. *
  538. * INPUT
  539. *
  540. * OUTPUT
  541. *
  542. * RETURNS
  543. *
  544. * AUTHOR
  545. *
  546. *   Alexander Enzmann
  547. *
  548. * DESCRIPTION
  549. *
  550. *   -
  551. *
  552. * CHANGES
  553. *
  554. *   -
  555. *
  556. ******************************************************************************/
  557.  
  558. static int Inside_Box(IPoint, Object)
  559. VECTOR IPoint;
  560. OBJECT *Object;
  561. {
  562.   VECTOR New_Point;
  563.   BOX *box = (BOX *) Object;
  564.  
  565.   /* Transform the point into box space. */
  566.  
  567.   if (box->Trans != NULL)
  568.   {
  569.     MInvTransPoint(New_Point, IPoint, box->Trans);
  570.   }
  571.   else
  572.   {
  573.     Assign_Vector(New_Point,IPoint);
  574.   }
  575.  
  576.   /* Test to see if we are outside the box. */
  577.  
  578.   if ((New_Point[X] < box->bounds[0][X]) || (New_Point[X] > box->bounds[1][X]))
  579.   {
  580.     return (Test_Flag(box, INVERTED_FLAG));
  581.   }
  582.  
  583.   if ((New_Point[Y] < box->bounds[0][Y]) || (New_Point[Y] > box->bounds[1][Y]))
  584.   {
  585.     return (Test_Flag(box, INVERTED_FLAG));
  586.   }
  587.  
  588.   if ((New_Point[Z] < box->bounds[0][Z]) || (New_Point[Z] > box->bounds[1][Z]))
  589.   {
  590.     return (Test_Flag(box, INVERTED_FLAG));
  591.   }
  592.  
  593.   /* Inside the box. */
  594.  
  595.   return (!Test_Flag(box, INVERTED_FLAG));
  596. }
  597.  
  598.  
  599.  
  600. /*****************************************************************************
  601. *
  602. * FUNCTION
  603. *
  604. *   Box_Normal
  605. *
  606. * INPUT
  607. *
  608. * OUTPUT
  609. *
  610. * RETURNS
  611. *
  612. * AUTHOR
  613. *
  614. *   Alexander Enzmann
  615. *
  616. * DESCRIPTION
  617. *
  618. *   -
  619. *
  620. * CHANGES
  621. *
  622. *   -
  623. *
  624. ******************************************************************************/
  625.  
  626. static void Box_Normal(Result, Object, Inter)
  627. OBJECT *Object;
  628. VECTOR Result;
  629. INTERSECTION *Inter;
  630. {
  631.   switch (Inter->i1)
  632.   {
  633.     case SIDE_X_0: Make_Vector(Result, -1.0,  0.0,  0.0); break;
  634.     case SIDE_X_1: Make_Vector(Result,  1.0,  0.0,  0.0); break;
  635.     case SIDE_Y_0: Make_Vector(Result,  0.0, -1.0,  0.0); break;
  636.     case SIDE_Y_1: Make_Vector(Result,  0.0,  1.0,  0.0); break;
  637.     case SIDE_Z_0: Make_Vector(Result,  0.0,  0.0, -1.0); break;
  638.     case SIDE_Z_1: Make_Vector(Result,  0.0,  0.0,  1.0); break;
  639.  
  640.     default: Error("Unknown box side in Box_Normal().\n");
  641.   }
  642.  
  643.   /* Transform the point into the boxes space. */
  644.  
  645.   if (((BOX *)Object)->Trans != NULL)
  646.   {
  647.     MTransNormal(Result, Result, ((BOX *)Object)->Trans);
  648.  
  649.     VNormalize(Result, Result);
  650.   }
  651. }
  652.  
  653.  
  654.  
  655. /*****************************************************************************
  656. *
  657. * FUNCTION
  658. *
  659. *   Translate_Box
  660. *
  661. * INPUT
  662. *
  663. * OUTPUT
  664. *
  665. * RETURNS
  666. *
  667. * AUTHOR
  668. *
  669. *   Alexander Enzmann
  670. *
  671. * DESCRIPTION
  672. *
  673. *   -
  674. *
  675. * CHANGES
  676. *
  677. *   -
  678. *
  679. ******************************************************************************/
  680.  
  681. static void Translate_Box(Object, Vector, Trans)
  682. OBJECT *Object;
  683. VECTOR Vector;
  684. TRANSFORM *Trans;
  685. {
  686.   if (((BOX *)Object)->Trans == NULL)
  687.   {
  688.     VAddEq(((BOX *)Object)->bounds[0], Vector);
  689.  
  690.     VAddEq(((BOX *)Object)->bounds[1], Vector);
  691.  
  692.     Compute_Box_BBox((BOX *)Object);
  693.   }
  694.   else
  695.   {
  696.     Transform_Box(Object, Trans);
  697.   }
  698. }
  699.  
  700.  
  701.  
  702. /*****************************************************************************
  703. *
  704. * FUNCTION
  705. *
  706. *   Rotate_Box
  707. *
  708. * INPUT
  709. *
  710. * OUTPUT
  711. *
  712. * RETURNS
  713. *
  714. * AUTHOR
  715. *
  716. *   Alexander Enzmann
  717. *
  718. * DESCRIPTION
  719. *
  720. *   -
  721. *
  722. * CHANGES
  723. *
  724. *   -
  725. *
  726. ******************************************************************************/
  727.  
  728. static void Rotate_Box(Object, Vector, Trans)
  729. OBJECT *Object;
  730. VECTOR Vector;
  731. TRANSFORM *Trans;
  732. {
  733.   Transform_Box(Object, Trans);
  734. }
  735.  
  736.  
  737.  
  738. /*****************************************************************************
  739. *
  740. * FUNCTION
  741. *
  742. *   Scale_Box
  743. *
  744. * INPUT
  745. *
  746. * OUTPUT
  747. *
  748. * RETURNS
  749. *
  750. * AUTHOR
  751. *
  752. *   Alexander Enzmann
  753. *
  754. * DESCRIPTION
  755. *
  756. *   -
  757. *
  758. * CHANGES
  759. *
  760. *   -
  761. *
  762. ******************************************************************************/
  763.  
  764. static void Scale_Box(Object, Vector, Trans)
  765. OBJECT *Object;
  766. VECTOR Vector;
  767. TRANSFORM *Trans;
  768. {
  769.   DBL temp;
  770.   BOX *Box = (BOX *)Object;
  771.  
  772.   if (((BOX *)Object)->Trans == NULL)
  773.   {
  774.     VEvaluateEq(Box->bounds[0], Vector);
  775.     VEvaluateEq(Box->bounds[1], Vector);
  776.  
  777.     if (Box->bounds[0][X] > Box->bounds[1][X])
  778.     {
  779.       temp = Box->bounds[0][X];
  780.  
  781.       Box->bounds[0][X] = Box->bounds[1][X];
  782.       Box->bounds[1][X] = temp;
  783.     }
  784.  
  785.     if (Box->bounds[0][Y] > Box->bounds[1][Y])
  786.     {
  787.       temp = Box->bounds[0][Y];
  788.  
  789.       Box->bounds[0][Y] = Box->bounds[1][Y];
  790.       Box->bounds[1][Y] = temp;
  791.     }
  792.  
  793.     if (Box->bounds[0][Z] > Box->bounds[1][Z])
  794.     {
  795.       temp = Box->bounds[0][Z];
  796.  
  797.       Box->bounds[0][Z] = Box->bounds[1][Z];
  798.       Box->bounds[1][Z] = temp;
  799.     }
  800.  
  801.     Compute_Box_BBox((BOX *)Object);
  802.   }
  803.   else
  804.   {
  805.     Transform_Box(Object, Trans);
  806.   }
  807. }
  808.  
  809.  
  810.  
  811. /*****************************************************************************
  812. *
  813. * FUNCTION
  814. *
  815. *   Invert_Box
  816. *
  817. * INPUT
  818. *
  819. * OUTPUT
  820. *
  821. * RETURNS
  822. *
  823. * AUTHOR
  824. *
  825. *   Alexander Enzmann
  826. *
  827. * DESCRIPTION
  828. *
  829. *   -
  830. *
  831. * CHANGES
  832. *
  833. *   -
  834. *
  835. ******************************************************************************/
  836.  
  837. static void Invert_Box(Object)
  838. OBJECT *Object;
  839. {
  840.   Invert_Flag(Object, INVERTED_FLAG);
  841. }
  842.  
  843.  
  844.  
  845. /*****************************************************************************
  846. *
  847. * FUNCTION
  848. *
  849. *   Transform_Box
  850. *
  851. * INPUT
  852. *
  853. * OUTPUT
  854. *
  855. * RETURNS
  856. *
  857. * AUTHOR
  858. *
  859. *   Alexander Enzmann
  860. *
  861. * DESCRIPTION
  862. *
  863. *   -
  864. *
  865. * CHANGES
  866. *
  867. *   -
  868. *
  869. ******************************************************************************/
  870.  
  871. static void Transform_Box(Object, Trans)
  872. OBJECT *Object;
  873. TRANSFORM *Trans;
  874. {
  875.   BOX *box = (BOX *)Object;
  876.  
  877.   if (box->Trans == NULL)
  878.   {
  879.     box->Trans = Create_Transform();
  880.   }
  881.  
  882.   Compose_Transforms(box->Trans, Trans);
  883.  
  884.   Compute_Box_BBox(box);
  885. }
  886.  
  887.  
  888.  
  889. /*****************************************************************************
  890. *
  891. * FUNCTION
  892. *
  893. *   Create_Box
  894. *
  895. * INPUT
  896. *
  897. * OUTPUT
  898. *
  899. * RETURNS
  900. *
  901. * AUTHOR
  902. *
  903. *   Alexander Enzmann
  904. *
  905. * DESCRIPTION
  906. *
  907. *   -
  908. *
  909. * CHANGES
  910. *
  911. *   -
  912. *
  913. ******************************************************************************/
  914.  
  915. BOX *Create_Box()
  916. {
  917.   BOX *New;
  918.  
  919.   New = (BOX *)POV_MALLOC(sizeof(BOX), "box");
  920.  
  921.   INIT_OBJECT_FIELDS(New, BOX_OBJECT, &Box_Methods)
  922.  
  923.   Make_Vector(New->bounds[0], -1.0, -1.0, -1.0);
  924.   Make_Vector(New->bounds[1],  1.0,  1.0,  1.0);
  925.  
  926.   Make_BBox(New->BBox, -1.0, -1.0, -1.0, 2.0, 2.0, 2.0);
  927.  
  928.   New->Trans = NULL;
  929.  
  930.   return (New);
  931. }
  932.  
  933.  
  934.  
  935. /*****************************************************************************
  936. *
  937. * FUNCTION
  938. *
  939. *   Copy_Box
  940. *
  941. * INPUT
  942. *
  943. * OUTPUT
  944. *
  945. * RETURNS
  946. *
  947. * AUTHOR
  948. *
  949. *   Alexander Enzmann
  950. *
  951. * DESCRIPTION
  952. *
  953. *   -
  954. *
  955. * CHANGES
  956. *
  957. *   -
  958. *
  959. ******************************************************************************/
  960.  
  961. void *Copy_Box(Object)
  962. OBJECT *Object;
  963. {
  964.   BOX *New;
  965.  
  966.   New  = Create_Box();
  967.  
  968.   /* Copy box. */
  969.  
  970.   *New = *((BOX *)Object);
  971.  
  972.   New->Trans = Copy_Transform(((BOX *)Object)->Trans);
  973.  
  974.   return (New);
  975. }
  976.  
  977.  
  978.  
  979. /*****************************************************************************
  980. *
  981. * FUNCTION
  982. *
  983. *   Destroy_Box
  984. *
  985. * INPUT
  986. *
  987. * OUTPUT
  988. *
  989. * RETURNS
  990. *
  991. * AUTHOR
  992. *
  993. *   Alexander Enzmann
  994. *
  995. * DESCRIPTION
  996. *
  997. *   -
  998. *
  999. * CHANGES
  1000. *
  1001. *   -
  1002. *
  1003. ******************************************************************************/
  1004.  
  1005. void Destroy_Box(Object)
  1006. OBJECT *Object;
  1007. {
  1008.   Destroy_Transform(((BOX *)Object)->Trans);
  1009.  
  1010.   POV_FREE (Object);
  1011. }
  1012.  
  1013.  
  1014.  
  1015. /*****************************************************************************
  1016. *
  1017. * FUNCTION
  1018. *
  1019. *   Compute_Box_BBox
  1020. *
  1021. * INPUT
  1022. *
  1023. *   Box - Box
  1024. *
  1025. * OUTPUT
  1026. *
  1027. *   Box
  1028. *
  1029. * RETURNS
  1030. *
  1031. * AUTHOR
  1032. *
  1033. *   Dieter Bayer
  1034. *
  1035. * DESCRIPTION
  1036. *
  1037. *   Calculate the bounding box of a box.
  1038. *
  1039. * CHANGES
  1040. *
  1041. *   Aug 1994 : Creation.
  1042. *
  1043. ******************************************************************************/
  1044.  
  1045. void Compute_Box_BBox(Box)
  1046. BOX *Box;
  1047. {
  1048.   Assign_BBox_Vect(Box->BBox.Lower_Left, Box->bounds[0]);
  1049.  
  1050.   VSub(Box->BBox.Lengths, Box->bounds[1], Box->bounds[0]);
  1051.  
  1052.   if (Box->Trans != NULL)
  1053.   {
  1054.     Recompute_BBox(&Box->BBox, Box->Trans);
  1055.   }
  1056. }
  1057.  
  1058.